/*
 * Copyright (c) 2016  西咸新区大数据信息技术服务有限公司版权所有.
 */
package priv.conceit.sc.hoxton.common.util;


import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Objects;

/**
 * 文件转换工具类
 *
 * @author Conceit
 * 2017-01-07 添加方法 fileCastToByteArray
 * 2017-01-07 添加方法 inputStreamCastToByteArray
 * 2017-09-07 添加方法 fileCastToByteArrayUseMappedByteBuffer
 * 2020-04-22 添加方法 toByteArray {@linkplain IoUtil#toByteArray(InputStream)}
 * 2020-04-22 更新方法 toByteArray {@linkplain IoUtil#toByteArray(File)}
 * 2020-04-22 更新方法 toByteArrayUseFileChannel {@linkplain IoUtil#toByteArrayUseFileChannel(File)}
 * @since 1.0.0, 2017/08/21
 */
@Slf4j
public class IoUtil {

	/**
	 * 将文件file类转换为二进制数组
	 *
	 * @param file 需要转换的文件类
	 * @return byte数组
	 */
	public static byte[] toByteArray(File file) {
		//形参合法性校验
		if (file == null || !file.exists()) {
			return null;
		}
		//使用2^N大小的内存,避免产生碎片 底层数据为1024为一个单位进行储存
		byte[] result;
		FileInputStream fileInputStream;
		ByteArrayOutputStream byteArrayOutputStream;
		try {
			fileInputStream = new FileInputStream(file);
			byteArrayOutputStream = new ByteArrayOutputStream();
			int n;
			//每次读取一个byte 读取到最后一个byte 就返回-1 循环结束
			//n不是循环的index
			while ((n = fileInputStream.read()) != -1) {
				byteArrayOutputStream.write(n);
			}
			fileInputStream.close();
			byteArrayOutputStream.close();
			result = byteArrayOutputStream.toByteArray();
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		return result;
	}

	/**
	 * 输入流转换为byteArray
	 * BufferedInputStream 每次读取指定的长度 放入内存 减少io操作
	 *
	 * @param inputStream 输入流
	 * @return byte数组
	 */
	public static byte[] toByteArray(InputStream inputStream) {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024 * 4];
		int eof = -1;
		//the number of bytes to write
		int readByteNum;
		try {
			while ((readByteNum = inputStream.read(buffer)) != eof) {
				output.write(buffer, 0, readByteNum);
			}
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
		return output.toByteArray();
	}


	/**
	 * 文件转换为byteArray
	 * 使用MappedByteBuffer 可以在处理大文件时，提升性能
	 *
	 * @param file 形参所指向的文件对象
	 * @return byte[]
	 */
	public static byte[] toByteArrayUseFileChannel(File file) {
		//形参合法性校验
		if ((Objects.isNull(file)) || !file.exists()) {
			return null;
		}
		FileChannel fileChannel = null;
		try {
			fileChannel = new RandomAccessFile(file, "r").getChannel();
			MappedByteBuffer byteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0,
					fileChannel.size()).load();

			byte[] result = new byte[(int) fileChannel.size()];
			if (byteBuffer.remaining() > 0) {
				byteBuffer.get(result, 0, byteBuffer.remaining());
			}
			return result;
		} catch (IOException e) {
			e.printStackTrace();

			return null;
		} finally {
			try {
				fileChannel.close();
			} catch (IOException | NullPointerException e) {
				e.printStackTrace();
			}
		}
	}



}
